/*
 * Copyright (c) 2007 Team and Concepts Limited.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *     * Neither the name of the Team and Concepts Limited nor the
 *       names of its contributors may be used to endorse or promote products
 *       derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY TEAM AND CONCEPTS LIMITED ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL TEAM AND CONCEPTS LIMITED BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.IO;
using System.Xml;
using System.Net.Cache;
using EditGrid.API.Client.Atom;

namespace EditGrid.API.Client
{
    //////////////////////////////////////////////////////////////////////
    /// <summary>Wrapper class to .Net HttpWebRequest</summary> 
    //////////////////////////////////////////////////////////////////////
    internal class EditGridHttpRequest
    {
        private string apiToken;
        private string appId;
        private HttpWebRequest req;
        private Stream requestBodyStream;
        private static IWebProxy proxy = null;
        private static ICredentials credentials = null;

        public EditGridHttpRequest(string method, Uri uri, string appId)
        {
            if (uri.Query == "")
            {
                uri = new Uri(uri.ToString() + "?app=" + appId);
            }
            else
            {
                uri = new Uri(uri.ToString() + "&app=" + appId);
            }
            req = (HttpWebRequest)HttpWebRequest.Create(uri);
            req.Accept = "";
            req.Method = method;
            req.KeepAlive = false;
            req.ServicePoint.Expect100Continue = false;
            req.Proxy = proxy;
            req.Credentials = credentials;
            req.CachePolicy = new RequestCachePolicy(RequestCacheLevel.NoCacheNoStore);
            req.Pipelined = false;
            req.SendChunked = false;
            req.ProtocolVersion = new Version(1, 0);
            this.appId = appId;
        }

        public static IWebProxy Proxy
        {
            get { return proxy; }
            set { proxy = value; }
        }

        public static ICredentials Credentials
        {
            get { return credentials; }
            set { credentials = value; }
        }

        public string ApiToken
        {
            get { return this.apiToken; }
            set { this.apiToken = value; }
        }

        public string AppId
        {
            get { return this.appId; }
        }

        public WebHeaderCollection Headers
        {
            get { return this.req.Headers; }
        }

        public string Method
        {
            get { return this.req.Method; }
        }

        public Uri RequestUri
        {
            get { return this.req.RequestUri; }
        }

        public string ContentType
        {
            get { return this.req.ContentType; }
            set { this.req.ContentType = value; }
        }

        public Stream RequestBodyStream
        {
            get { return this.requestBodyStream; }
        }

        public void SetRequestBody(byte[] value)
        {
            this.requestBodyStream = new MemoryStream(value);
        }

        public void SetRequestBody(string value)
        {
            UTF8Encoding encoding = new UTF8Encoding();
            byte[] bytes = encoding.GetBytes(value);
            this.requestBodyStream = new MemoryStream(bytes);
        }

        public void SetRequestBody(Stream stream)
        {
            this.requestBodyStream = stream;
        }

        public EditGridHttpResponse GetResponse()
        {
            if (this.apiToken != null)
            {
                this.Headers.Set("X-EditGrid-Authorization", this.apiToken);
            }

            if ((this.Method == "POST" || this.Method == "PUT") && this.requestBodyStream != null)
            {
                Stream postStream = this.req.GetRequestStream();
                byte[] buf = new byte[1024*1024];
                int read;
                while ((read = this.requestBodyStream.Read(buf, 0, buf.Length)) > 0) {
                    postStream.Write(buf, 0, read);
                }
                postStream.Close();
            }

            WebResponse webResponse = null;
            try
            {
                webResponse = this.req.GetResponse();
            }
            catch (WebException e)
            {   
                webResponse = e.Response;
                if (webResponse == null || e.Response.Headers.Get("X-EditGrid-API-Version") == null)
                {
                    throw e;
                }
            }
            return new EditGridHttpResponse((HttpWebResponse) webResponse);
        }
    }
}
